package cpr.command;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import cpr.DefaultCommandHandler;
import cpr.Printer;
import cpr.data.SplitCluster;

public class CmdSpectr extends DefaultCommandHandler {

	public CmdSpectr() {
		super("spectr","prints clusters size in logariphmic scale. requires splitby results",null,null);
	}
    public int boundCounter(int c, int bound) {
        int r = (c/bound+1)*bound;
        return r;
    }
    
    public int logBound(int c) {
    	double d = Math.log10(c);
    	int r = (int)d;
    	return r;
    }
    private String fixedWirdth(String s, int w) {
    	StringBuffer sb = new StringBuffer(w);
    	sb.append(s);
    	while(sb.length()<w) {
    		sb.append(" ");
    	}
    	return sb.toString();
    	
    }
    public void execute(String[] params) {
    	int bound = Integer.parseInt( getParameter(params,1,"10000"));
    	if (bound!=10000) {
    		execute2(params);
    	} else {
    		Set set = getCommandContext().getContext().getCurrentWorksetContext().getClusterSet();
            Map counterMap = new HashMap();
            int min = -1;
            int max = -1;
            int sum = 0;
            for (Iterator iter = set.iterator(); iter.hasNext();) {
                SplitCluster c =  (SplitCluster)iter.next();
                Integer value = Integer.valueOf(logBound(c.getCounter()));
                Integer m = (Integer)counterMap.get(value);
                if (m==null) {
                    m = new Integer(0);
                }
                if ((min==-1)||(min>c.getCounter())) {
                	min = c.getCounter();
                }
                if (max<c.getCounter()) {
                	max = c.getCounter();
                }
                sum = sum + c.getCounter();
                Integer newM = new Integer(m.intValue()+1);
                counterMap.put(value, newM);
               
    		}
            
            List l = new ArrayList();
            l.addAll(counterMap.keySet());
            Collections.sort(l);
            for (Iterator iter = l.iterator(); iter.hasNext();) {
                Integer c = (Integer)iter.next();

                String minValue = fixedWirdth(""+(int)Math.exp(c.intValue()*Math.log(10)),4);
                String maxValue = fixedWirdth(""+ ((int)Math.exp((c.intValue()+1)*(Math.log(10)))-1)  ,5);
                
                Integer m = (Integer)counterMap.get(c);
                Printer.println(minValue+ " "+maxValue+"\t"+m);
            }
            Printer.println("min: "+min+"\tmax: "+max+"\tsum: "+sum+"\tcount: "+set.size());
            
    	}
    }
    	
	public void execute2(String[] params) {
		int bound = Integer.parseInt( getParameter(params,1,"10000"));
	
        Set set = getCommandContext().getContext().getCurrentWorksetContext().getClusterSet();
        
        
        
        Map counterMap = new HashMap();
        for (Iterator iter = set.iterator(); iter.hasNext();) {
            SplitCluster c =  (SplitCluster)iter.next();
            
            Integer cb = new Integer(boundCounter(c.getCounter(),bound));
            
            Integer m = (Integer)counterMap.get(cb);
            if (m==null) {
                m = new Integer(0);
            }
            Integer newM = new Integer(m.intValue()+1);
            counterMap.put(cb, newM);
           
        }
        List l = new ArrayList();
        l.addAll(counterMap.keySet());
        Collections.sort(l);
        for (Iterator iter = l.iterator(); iter.hasNext();) {
            Integer c = (Integer)iter.next();
            Integer m = (Integer)counterMap.get(c);
            Printer.println(c+"\t"+m);
        }
        
   }
	
}
